using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.InsightUtilities;

namespace PHSRAG.Insight21.Admin.Controls
{
	/// <summary>
	///	Allows giving and revoking user's access to a lab.
	/// </summary>
	public partial class EditAdminLabAccess : System.Web.UI.UserControl
	{
		#region Constants
		/// <summary>Key used to place users object in the page hashtable.</summary>
		private const string	UsersKey					= "Users_B840A82C-F599-4863-8243-A1351D9C7E5F";
		/// <summary>Key used to place username search criteria in the page hashtable.</summary>
		private const string	UsernameKey					= "Username_B840A82C-F599-4863-8243-A1351D9C7E5F";
		/// <summary>Key used to place last name search criteria in the page hashtable.</summary>
		private const string	LastNameKey					= "LastName_B840A82C-F599-4863-8243-A1351D9C7E5F";
		/// <summary>Key used to place first name search criteria in the page hashtable.</summary>
		private const string	FirstNameKey				= "FirstName_B840A82C-F599-4863-8243-A1351D9C7E5F";
		/// <summary>Passed into the user object load method to retrieve registered users only.</summary>
		private const int		IncludeUnregisteredUsersBit = 0;
		/// <summary>Sort expression used to sort users.</summary>
		private const string UsersSortExpression = "LastName ASC";
		/// <summary>Key used to check if the control is loaded for the first time or as a result of a client postback.</summary>
		private const string ControlPostBackKey = "ControlPostBackKey_B840A82C-F599-4863-8243-A1351D9C7E5F";
		#endregion

		#region Private Variables
		/// <summary>Policy used for caching business objects.</summary>
		private	Policy.ICachePolicy		objectCachePolicy;
		/// <summary>The reference to the containing page of this user control. </summary>
		private EditAdminLabAccessWizard			hostPage;
		#endregion

		#region Private Properties
		/// <summary>
		/// Gets a list of available users. Checks the cache first, if empty
		/// retrieves it from the database.
		/// </summary>
		private Users AvailableUsers 
		{
			get 
			{
				Users users = hostPage.EditLabWizardPageInfo[UsersKey] as Users;
				if (users == null) 
				{
					users = new Users(objectCachePolicy);
					users.Load(Utility.DataAccess.ConnectionString, UsersSortExpression,
						ResultSetType.Full, userName.Text.Trim(),
						lastName.Text.Trim(), firstName.Text.Trim(),
						IncludeUnregisteredUsersBit);
					hostPage.EditLabWizardPageInfo[UsersKey] = users;

					// cache the modified hash table
					hostPage.EditLabWizardPageInfo = hostPage.EditLabWizardPageInfo;
				}
				return users;
			}
		}

		/// <summary>
		/// Enables/Disables validation of users search criteria textboxes.
		/// </summary>
		public bool EnableSearchCriteriaValidation
		{
			set { validateCriteria.Enabled = value; }	
		}

		/// <summary>
		/// Reinforces the notion of "IsPostBack" within this user control as UserControl.IsPostBack
		/// is the same as Page.IsPostBack which will not work in this case because we have one page and
		/// multiple controls.
		/// </summary>
		private bool IsUserControlPostBack 
		{
			get { return ViewState[ControlPostBackKey] != null; }
			set { ViewState.Add(ControlPostBackKey, value); }
		}
		#endregion

		#region Event Handlers
		/// <summary>
		/// Occurs when the page is loaded.
		/// </summary>
		/// <param name="sender">The object raising an event.</param>
		/// <param name="e">Argument associated with the event</param>
		protected void Page_Load(object sender, System.EventArgs e)
		{
			hostPage = (EditAdminLabAccessWizard)Page;
			if (!IsUserControlPostBack) 
			{
				LoadAssignedUserList(hostPage.CurrentLab);
				IsUserControlPostBack = true;
			}
		}
		/// <summary>
		/// Loads the available user listbox.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnSearch(object sender, EventArgs e)
		{
			validateUsers.IsValid = true;
			if (Page.IsValid) 
			{
				// remove the users from cache so as to instigate a new search in the database
				hostPage.EditLabWizardPageInfo.Remove(UsersKey);

				LoadAvailableUserList();
			}
		}
		
		/// <summary>
		/// Removes selected item(s) from available list and adds them to assigned list.
		/// Also keeps in-memory assigned and available lists in sync with the changes.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnAdd(object sender, EventArgs e)
		{
			if (availableList.Items.Count != 0)
			{
				ListItem item = null;
				Lab lab = hostPage.CurrentLab;
				DataTable assignedListDataTable = lab.Access;
				DataTable availableListDataTable = hostPage.EditLabWizardPageInfo[UsersKey] != null ? AvailableUsers.GetDataContainer().Tables[0] : null;		
				while ((item = availableList.SelectedItem) != null)
				{
					item.Selected = false;
					assignedList.Items.Add(item);
					availableList.Items.Remove(item);

					DataRow newRow = assignedListDataTable.NewRow();
					assignedListDataTable.Rows.Add(newRow);
					newRow["PersonId"] = Convert.ToInt32(item.Value);
					newRow["LabId"] = lab.Id;
					newRow["PIName"] = item.Text;
					if (availableListDataTable != null)
						availableListDataTable.Rows.Remove(
							availableListDataTable.Select(string.Format("PersonId = {0}", item.Value))[0]);	
				}
				if (availableListDataTable != null)
					AvailableUsers.Cache();
			}
		}
		
		/// <summary>
		/// Removes selected items from assigned list and adds them to available list.
		/// Also keeps in-memory assigned and available lists in sync with the changes.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnRemove(object sender, EventArgs e)
		{
			ListItem item = null;
			DataTable assignedListDataTable = hostPage.CurrentLab.Access;
			DataTable availableListDataTable = hostPage.EditLabWizardPageInfo[UsersKey] != null ? AvailableUsers.GetDataContainer().Tables[0] : null;
			while ((item = assignedList.SelectedItem) != null) 
			{
				item.Selected = false;
				availableList.Items.Add(item);
				assignedList.Items.Remove(item);
				if (availableListDataTable != null) 
				{					
					DataRow newRow = availableListDataTable.NewRow();				
					availableListDataTable.Rows.Add(newRow);
					string[] name = item.Text.Split(' ');
					newRow["LastName"] = name[1];
					newRow["FirstName"] = name[0];
					newRow["PersonId"] = Convert.ToInt32(item.Value);
				}
				assignedListDataTable.Select(string.Format("PersonId = {0}", item.Value))[0].Delete();
			}
			if (availableListDataTable != null)
				AvailableUsers.Cache();
		}
		/// <summary>
		/// Ensures that at least one of the search criteria values has been provided. 
		/// </summary>
		/// <param name="source">The object raising an event.</param>
		/// <param name="args">Information accompanying the event itself.</param>
		protected void OnValidateCriteria(object source, System.Web.UI.WebControls.ServerValidateEventArgs args)
		{
			args.IsValid = userName.Text.Trim() != string.Empty || firstName.Text.Trim() != string.Empty || 
				lastName.Text.Trim() != string.Empty;
		}
		/// <summary>
		/// Ensures that at least one user is assigned to the lab. 
		/// </summary>
		/// <param name="source">The object raising an event.</param>
		/// <param name="args">Information accompanying the event itself.</param>
		protected void OnValidateUsers(object source, ServerValidateEventArgs args)
		{
			args.IsValid = (assignedList.Items.Count != 0);
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Loads the assigned user list.
		/// </summary>
		/// <param name="lab">The reference to a lab object whose data container
		///  has assigned users.</param>
		private void LoadAssignedUserList(Lab lab)
		{
			DataTable assignedUsersDataTable = lab.Access;
			foreach (DataRow userRow in assignedUsersDataTable.Rows)
				assignedList.Items.Add(new ListItem(userRow["PIName"].ToString(), Convert.ToString(userRow["PersonId"])));
		}
		/// <summary>
		/// Loads availabe user list.
		/// </summary>
		private void LoadAvailableUserList() 
		{
			availableList.Items.Clear();
			DataTable userDataTable = AvailableUsers.GetDataContainer().Tables[0];
			foreach (DataRow userRow in userDataTable.Rows) 
			{
				string assignedListValue = Convert.ToString(userRow["PersonId"]);
				if (assignedList.Items.FindByValue(assignedListValue) == null)
					availableList.Items.Add(new ListItem(
						string.Format("{0} {1}", userRow["FirstName"], userRow["LastName"]),
						assignedListValue));
			}
		}
		#endregion

		#region Web Form Designer generated code
		/// <summary>
		/// Wires up page events.
		/// </summary>
		/// <param name="e">Information associated with the event.</param>
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);

			objectCachePolicy = (Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey];

			ID = "editAdminLabAccess";

		}
		
		/// <summary>
		///		Required method for Designer support - do not modify
		///		the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
		}
		#endregion
	}
}
